package org.jvm.nativemethod.methods.sun.reflect;

import org.jvm.nativemethod.NativeMethodRegister;
import org.jvm.rtda.Object;
import org.jvm.rtda.heap.Klass;
import org.jvm.rtda.thread.*;

import java.util.Stack;

/**
 * @author 海燕
 * @date 2023/2/26
 */
public class ReflectionNativeMethod extends NativeMethodRegister {

    public static void init() throws NoSuchMethodException {
        register("sun/reflect/Reflection", "getCallerClass", "()Ljava/lang/Class;", ReflectionNativeMethod.class.getDeclaredMethod("getCallerClass", Frame.class));
        register("sun/reflect/Reflection", "getClassAccessFlags", "(Ljava/lang/Class;)I", ReflectionNativeMethod.class.getDeclaredMethod("getClassAccessFlags", Frame.class));
    }

    public static void getCallerClass(Frame frame) {
        Stack<Frame> frameStack = frame.getThread().getStack().getStack();
        Frame callerFrame = frameStack.get(frameStack.size() - 1 - 2);
        Object callerClass = callerFrame.getMethod().getKlass().getjClass();
        frame.getOperandStack().pushRef(callerClass);
    }

    public static void getClassAccessFlags(Frame frame) {
        LocalVars vars = frame.getLocalVars();
        Object type = vars.getRef(0);
        Klass klass = (Klass) type.getExtra();
        int flags = klass.getAccessFlags();
        frame.getOperandStack().pushInt(flags);
    }

}
